#
最近试着用Swift基于AudioQueue写一个音乐播放器,但是AudioQueue的API都是C函数,避免不了操作指针。经常卡在指针上,于是决定先静下心来学习一下Swift中的指针。baidu了很多,但是没有系统讲解Swift指针的文章,一边学一边记录,写下这些作为积累。这次学习分为四个部分:UnsafePointer, UnsafeMutablePointer, UnsafeRawPointer, UnsafeMutableRawPointer。有不对的地方欢迎指出!
在Swift中,指针由结构体 struct UnsafePointer<Pointee> 或 struct UnsafeMutablePointer<Pointee> 表示,但是不能通过”&”获取一个UnsafePointer 或 UnsafeMutablePointer的实例,只能作为inout参数使用。UnsafePointer相对于UnsafeMutablePointer,其所指向的地址的值是不可变的
一、UnsafeMutablePointer
被UnsafeMutablePointe引用的内存有三种状态:
\1. Not Allocated
\2. Allocated but not initialized
\3. Allocated and initialized
只有在状态3时,可以安全的使用pointee属性来set和get。
1.初始化
allocate() initialize() deinitialize deallocate() 这四个方法来管理这个指针,并确保指针的pointee不会出错
(1) allocate
1 | let a_unsafe_mutable_pointer = UnsafeMutablePointer<Int>.allocate(capacity: 0)1 |
Tips:
\1. 需要指明要声明的指针类型
allocate是静态方法
(2) initialize
1 | a_unsafe_mutable_pointer.initialize(to: 5) |
这两种方法的结果是相同的
(3) deinitialize
1 | a_unsafe_mutable_pointer.deinitialize(count: 1)1 |
该方法貌似没有真正deintialize,只是返回了一个指向相同地址的UnsafeMutableRawPointer,并且a_unsafe_mutable_pointer.pointee仍然是可以正常使用
(4) deallocate
1 | a_unsafe_mutable_pointer.deallocate(capacity: 1)1 |
此时a_unsafe_mutable_pointer不可用了。
2.互相转化
(1) UnsafeMutablePointer -> Swift
1 | let a : Int = a_unsafe_mutable_pointer.pointee1 |
(2) Swift -> UnsafeMutablePointer
1 | let a : UnsafeMutablePointer = &a 1 |
以上代码是错误的,只能作为函数参数使用,如下所示
1 | func printPointer(ptr:UnsafeMutablePointer<Int>) { |
3.暂时绑定
将该内存暂时绑定为一种类型,例子中将Int型绑定为Int8
1 | a_unsafe_mutable_pointer.initialize(to: 0x0102030A) |
二、UnsafePointer
UnsafePointer中的pointee属性只能get不能set。UnsafePointer中没有allocate方法。
1.初始化
1 | let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)1 |
可以由UnsafeMutablePointer、OpaquePointer或其他UnsafePointer创建一个UnsafePointer指针。其他与UnsafeMutablePointer类似
2.互相转换
(1) UnsafeMutablePointer -> UnsafePointer
1 | let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)1 |
(2) UnsafePointer -> UnsafeMutablePointer
1 | let a_unsafe_mutable_pointer = UnsafePointer<Int>.init(mutating:a_unsafe_pointer)1 |
(3) UnsafePointer -> Swift
1 | let a : Int = a_unsafe_pointer.pointee1 |
(4) Swift -> UnsafePointer
与UnsafeMutablePointer类似,只能作为函数参数引用
3.withUnsafePointer方法
withUnsafePointer方法可以直接使用指针,但是不能改变pointee的值
1 | var a = 0 |
三、UnsafeMutableRawPointer
UnsafeMutableRawPointer按我的理解就是无类型的原始指针
1.分配内存
1 | var size = MemoryLayout<Int>.size |
这时,这个a_unsafe_mutable_raw_pointer感觉没啥用,还是需要转换为UnsafeMutablePointer来对内存进行操作。
2.初始化
初始化内存为Int类型,并赋值为1
1 | a_unsafe_mutable_raw_pointer.initializeMemory(as: Int.self, to: 1)1 |
3.绑定UnsafeMutablePointer
绑定了UnsafeMutablePointer,使用UnsafeMutablePointer才能对内存进行赋值,有两种方法绑定:
(1) bindMemory()
该方法绑定内存为指定类型并返回一个UnsafeMutablePointer<指定类型>的指针
1 | var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.bindMemory(to: Int.self, capacity: 1)1 |
(2) assumingMemoryBound()
该方法意思是直接转换这个原始指针为一个UnsafeMutablePointer<指定类型>的指针
1 | var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.assumingMemoryBound(to: Int.self)1 |
-
这样,就可以使用这个a_unsafe_mutable_pointer进行其他操作了。
4.deallocate
最后,需要释放内存,首先要deinitialize,再deallocate
1 | a_unsafe_mutable_pointer.deinitialize() |
5.转换
(1) Swift -> UnsafeMutableRawPointer
1 | var a = 10 |
(2) UnsafeMutableRawPointer -> Swift
其过程应当为UnsafeMutableRawPointer转换为UnsafeMutablePointer,再由UnsafeMutablePointer转换为Swift指针
四、UnsafeRawPointer
UnsafeRawPointer只能由其他指针用init方法得到,与UnsafePointer类似,没有allocate静态方法。但是,与UnsafeMutableRawPointer类似的有两种绑定方法,绑定成UnsafePointer指针。